package com.wxzz.elearing.course.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.wxzz.elearing.course.amqp.producer.CourseProducer;
import com.wxzz.elearing.course.dto.*;
import com.wxzz.elearing.course.entity.*;
import com.wxzz.elearing.course.mapper.CurriculumSectionTopicAnswerMapper;
import com.wxzz.elearing.course.mapper.CurriculumSectionTopicMapper;
import com.wxzz.elearing.course.mapper.TrainSurveyMapper;
import com.wxzz.elearing.course.mapper.WxUserTrainSurveyMapper;
import com.wxzz.elearing.course.service.ICurriculumSectionTopicService;
import com.wxzz.elearing.course.service.ITrainSurveyService;
import com.wxzz.elearing.course.service.openfeign.IWxUserApiFeign;
import com.wxzz.elearning.common.constants.RedisConstants;
import com.wxzz.elearning.common.dto.SystemMessageMqDto;
import com.wxzz.elearning.common.exception.ServiceException;
import com.wxzz.elearning.common.utils.ExcelTopicUtils;
import com.wxzz.elearning.common.utils.OpenFeignUtil;
import com.wxzz.elearning.common.vo.JgPageVo;
import com.wxzz.elearning.common.vo.ReturnVO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class TrainSurveyServiceImpl extends ServiceImpl<TrainSurveyMapper, TrainSurvey> implements ITrainSurveyService {

    @Autowired
    private TrainSurveyMapper trainSurveyMapper;

    @Autowired
    private CurriculumSectionTopicMapper curriculumSectionTopicMapper;

    @Autowired
    private CurriculumSectionTopicAnswerMapper curriculumSectionTopicAnswerMapper;

    @Autowired
    private CourseProducer courseProducer;

    @Override
    public ReturnVO saveTrainSurvey(TrainSurvey trainSurvey) {
        if (trainSurvey.getId() == null) {
            trainSurveyMapper.insert(trainSurvey);
        } else {
            //更新 将原有的试题删除重新添加
            trainSurveyMapper.updateById(trainSurvey);
            List<CurriculumSectionTopic> curriculumSectionTopics = curriculumSectionTopicMapper.selectList(new LambdaQueryWrapper<CurriculumSectionTopic>()
                    .eq(CurriculumSectionTopic::getCurriculumSectionId, trainSurvey.getId()));
            curriculumSectionTopics.forEach(curriculumSectionTopic -> {
                //删除试题
                curriculumSectionTopicMapper.deleteById(curriculumSectionTopic.getId());
                //删除答案
                curriculumSectionTopicAnswerMapper.deleteCurriculumSectionTopicAnswerByCurriculumSectionTopicId(curriculumSectionTopic.getId());
            });
        }
        //状态延迟修改
        courseProducer.trainSurveyUpdateStatus(trainSurvey.getId(), trainSurvey.getEndTime());
        if (trainSurvey.getCurriculumSectionTopics() != null) {
            //添加试题
            for (CurriculumSectionTopic curriculumSectionTopic : trainSurvey.getCurriculumSectionTopics()) {
                curriculumSectionTopic.setId(null);
                curriculumSectionTopic.setCurriculumSectionId(trainSurvey.getId());
                curriculumSectionTopic.setTopicCategory(2);
                curriculumSectionTopicMapper.insert(curriculumSectionTopic);
                if (curriculumSectionTopic.getCurriculumSectionTopicAnswerList() != null) {
                    //添加试题答案选项
                    curriculumSectionTopic.getCurriculumSectionTopicAnswerList().forEach(curriculumSectionTopicAnswer -> {
                        curriculumSectionTopicAnswer.setId(null);
                        curriculumSectionTopicAnswer.setCurriculumSectionTopicId(curriculumSectionTopic.getId());
                        curriculumSectionTopicAnswerMapper.insert(curriculumSectionTopicAnswer);
                    });
                }
            }
        }
        return new ReturnVO("新增或修改培训调查成功", trainSurvey.getId());
    }

    @Override
    public ReturnVO deleteTrainSurvey(Long trainSurveyId) {
        trainSurveyMapper.deleteById(trainSurveyId);
        return new ReturnVO("培训调查删除成功", trainSurveyId);
    }

    @Override
    public ReturnVO<JgPageVo<List<TrainSurvey>>> listTrainSurvey(Long enterpriseId, TrainSurveyDto trainSurveyDto) {
        PageHelper.startPage(trainSurveyDto.getCurPage(), trainSurveyDto.getMaxPage());
        QueryWrapper<TrainSurvey> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("enterprise_id", enterpriseId);
        queryWrapper.orderByDesc("create_time");
        if (trainSurveyDto.getStatus() != null) {
            queryWrapper.eq("status", trainSurveyDto.getStatus());
        }
        if (StringUtils.isNotBlank(trainSurveyDto.getSurveyTitle())) {
            queryWrapper.like("survey_title", trainSurveyDto.getSurveyTitle() + "%");
        }
        List<TrainSurvey> trainSurveys = trainSurveyMapper.selectList(queryWrapper);
        for (TrainSurvey trainSurvey : trainSurveys) {
            Integer count = wxUserTrainSurveyMapper.selectCount(new LambdaQueryWrapper<WxUserTrainSurvey>()
                    .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurvey.getId())
                    .eq(WxUserTrainSurvey::getExamStatus, 0)
                    .eq(WxUserTrainSurvey::getIsPass, 1));
            trainSurvey.setSurveyNum(count);
        }
        return new ReturnVO("培训调查列表", new JgPageVo<>(new PageInfo(trainSurveys)));
    }

    @Override
    public ReturnVO<JgPageVo<List<TrainSurvey>>> listTrainSurveyByWxUserId(Long wxUserId, TrainSurveyByWxUserDto trainSurveyByWxUserDto) {
        PageHelper.startPage(trainSurveyByWxUserDto.getCurPage(), trainSurveyByWxUserDto.getMaxPage());
//        QueryWrapper<TrainSurvey> queryWrapper = new QueryWrapper<>();
//        if (trainSurveyByWxUserDto.getStatus() != null) {
//            queryWrapper.eq("status", trainSurveyByWxUserDto.getStatus());
//        }
        List<TrainSurvey> trainSurveys = trainSurveyMapper.listTrainSurveyByWxUserId(wxUserId, trainSurveyByWxUserDto);
        for (TrainSurvey trainSurvey : trainSurveys) {
            //参与人数
            Integer count = wxUserTrainSurveyMapper.selectCount(new LambdaQueryWrapper<WxUserTrainSurvey>()
                    .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurvey.getId())
                    .eq(WxUserTrainSurvey::getExamStatus, 0)
                    .eq(WxUserTrainSurvey::getIsPass, 1));
            trainSurvey.setSurveyNum(count);
            //题目数量
            trainSurvey.setTopicsNum(curriculumSectionTopicMapper.selectCount(new LambdaQueryWrapper<CurriculumSectionTopic>()
                    .eq(CurriculumSectionTopic::getTopicCategory, 2)
                    .eq(CurriculumSectionTopic::getCurriculumSectionId, trainSurvey.getId())));
        }
        return new ReturnVO("查询当前用户培训调查成功", new JgPageVo<>(new PageInfo(trainSurveys)));
    }

    @Autowired
    private ICurriculumSectionTopicService curriculumSectionTopicService;

    @Override
    public ReturnVO<TrainSurvey> selectTrainSurveyDetail(Long trainSurveyId) {
        TrainSurvey trainSurvey = trainSurveyMapper.selectById(trainSurveyId);
        Optional.ofNullable(trainSurvey).orElseThrow(() -> new ServiceException("该培训调查已不存在"));
        //查询测评试题
        ReturnVO<List<CurriculumSectionTopic>> listReturnVO = curriculumSectionTopicService.listCurriculumSectionTopicByCurriculumSectionTopicId(trainSurveyId, 2);
        trainSurvey.setCurriculumSectionTopics(listReturnVO.getData());
        //参与人数
        Integer count = wxUserTrainSurveyMapper.selectCount(new LambdaQueryWrapper<WxUserTrainSurvey>()
                .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurvey.getId())
                .eq(WxUserTrainSurvey::getExamStatus, 0)
                .eq(WxUserTrainSurvey::getIsPass, 1));
        trainSurvey.setSurveyNum(count);
        return new ReturnVO("培训调查详情查询成功", trainSurvey);
    }

    @Autowired
    private IWxUserApiFeign wxUserApiFeign;

    @Override
    public ReturnVO<JgPageVo<List<WxUserTrainSurvey>>> selectWxUserTrainSurveyByTrainSurveyId(WxUserTrainSurveyDto wxUserTrainSurveyDto) {
        PageHelper.startPage(wxUserTrainSurveyDto.getCurPage(), wxUserTrainSurveyDto.getMaxPage());
        List<WxUserTrainSurvey> wxUserTrainSurveys = wxUserTrainSurveyMapper.selectList(new LambdaQueryWrapper<WxUserTrainSurvey>()
                .eq(WxUserTrainSurvey::getTrainSurveyId, wxUserTrainSurveyDto.getTrainSurveyId())
                .eq(WxUserTrainSurvey::getExamStatus, 0));
        for (WxUserTrainSurvey wxUserTrainSurvey : wxUserTrainSurveys) {
            //查询用户信息
            ReturnVO<String> stringReturnVO = wxUserApiFeign.selectWxUserByWxUserId(wxUserTrainSurvey.getWxUserId());
            JSONObject jsonObject = OpenFeignUtil.getJSONObject(stringReturnVO);
            wxUserTrainSurvey.setNickname(jsonObject.getString("nickname"));
            wxUserTrainSurvey.setIcon(jsonObject.getString("icon"));
            wxUserTrainSurvey.setPhone(jsonObject.getString("phone"));
            wxUserTrainSurvey.setOrganizationName(jsonObject.getString("organizationName"));
            wxUserTrainSurvey.setIdentityName(jsonObject.getString("identityName"));
        }
        return new ReturnVO("根据id查询培训调查人员", new JgPageVo<>(new PageInfo(wxUserTrainSurveys)));
    }

    @Override
    public ReturnVO<List<CurriculumSectionTopic>> listTrainSurveyByTrainSurveyHistory(Long wxUserId, Long trainSurveyId) {
        WxUserTrainSurvey wxUserTrainSurvey = wxUserTrainSurveyMapper.selectOne(new LambdaQueryWrapper<WxUserTrainSurvey>()
                .eq(WxUserTrainSurvey::getWxUserId, wxUserId)
                .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurveyId)
                .eq(WxUserTrainSurvey::getIsPass, 1));
        Optional.ofNullable(wxUserTrainSurvey).orElseThrow(() -> new ServiceException("您未完成该调查"));
        List<CurriculumSectionTopic> curriculumSectionTopics = Lists.newArrayList();
        if (StringUtils.isNotBlank(wxUserTrainSurvey.getTopicJson())) {
            curriculumSectionTopics = JSONObject.parseArray(wxUserTrainSurvey.getTopicJson(), CurriculumSectionTopic.class);
        }
        return new ReturnVO("调查记录查询成功", curriculumSectionTopics);
    }

    @Autowired
    private WxUserTrainSurveyMapper wxUserTrainSurveyMapper;

    @Override
    public ReturnVO saveWxUserTrainSurvey(WxUserTrainSurveyInsDto wxUserTrainSurveyInsDto) {
        TrainSurvey trainSurvey = trainSurveyMapper.selectById(wxUserTrainSurveyInsDto.getTrainSurveyId());
        Optional.ofNullable(trainSurvey).orElseThrow(() -> new ServiceException("该培训调查id对应培训不存在"));
        if (wxUserTrainSurveyInsDto.getWxUserIds() != null) {
            //先全部禁考
            List<WxUserTrainSurvey> wxUserTrainSurveys = wxUserTrainSurveyMapper.selectList(new LambdaQueryWrapper<WxUserTrainSurvey>()
                    .eq(WxUserTrainSurvey::getExamStatus, 0)
                    .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurvey.getId()));
            for (WxUserTrainSurvey wxUserTrainSurvey : wxUserTrainSurveys) {
                //禁考
                wxUserTrainSurvey.setExamStatus(1);
                wxUserTrainSurveyMapper.updateById(wxUserTrainSurvey);
            }
            //重新分配
            for (Long wxUserId : wxUserTrainSurveyInsDto.getWxUserIds()) {
                WxUserTrainSurvey wxUserTrainSurvey = wxUserTrainSurveyMapper.selectOne(new LambdaQueryWrapper<WxUserTrainSurvey>()
                        .eq(WxUserTrainSurvey::getTrainSurveyId, wxUserTrainSurveyInsDto.getTrainSurveyId())
                        .eq(WxUserTrainSurvey::getWxUserId, wxUserId));
                //如果不存在则添加上去
                if (wxUserTrainSurvey == null) {
                    WxUserTrainSurvey save = new WxUserTrainSurvey();
                    save.setTrainSurveyId(trainSurvey.getId());
                    save.setWxUserId(wxUserId);
                    wxUserTrainSurveyMapper.insert(save);
                } else {
                    //如果存在则直接改为可考
                    wxUserTrainSurvey.setExamStatus(0);
                    wxUserTrainSurveyMapper.updateById(wxUserTrainSurvey);
                }
            }
            //todo 小程序订阅
            SystemMessageMqDto systemMessageMqDto = new SystemMessageMqDto();
            systemMessageMqDto.setMessageDetail("您已被纳入" + trainSurvey.getSurveyTitle() + "培训调查中,请及时完成");
            systemMessageMqDto.setMessageTitle("培训调查");
            systemMessageMqDto.setWxUserIds(wxUserTrainSurveyInsDto.getWxUserIds());
            courseProducer.ackMQSender(JSONObject.toJSONString(systemMessageMqDto));
        }
        return new ReturnVO("分配考试人成功", trainSurvey);
    }


    @Override
    public ReturnVO<TrainSurvey> wxSelectTrainSurveyDetail(Long wxUserId, Long trainSurveyId) {
        TrainSurvey trainSurvey = trainSurveyMapper.selectById(trainSurveyId);
        Optional.ofNullable(trainSurvey).orElseThrow(() -> new ServiceException("该培训调查已不存在"));
        WxUserTrainSurvey wxUserTrainSurvey = wxUserTrainSurveyMapper.selectOne(new LambdaQueryWrapper<WxUserTrainSurvey>()
                .eq(WxUserTrainSurvey::getWxUserId, wxUserId)
                .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurveyId));
        Optional.ofNullable(wxUserTrainSurvey).ifPresent(e -> trainSurvey.setIsPass(e.getIsPass()));
        return new ReturnVO("培训调查详情查询成功", trainSurvey);
    }


    @Override
    public ReturnVO isPassTrainSurvey(Long wxUserId, TrainSurveyIsPassDto trainSurveyIsPassDto) {
        TrainSurvey trainSurvey = trainSurveyMapper.selectById(trainSurveyIsPassDto.getTrainSurveyId());
        Optional.ofNullable(trainSurvey).orElseThrow(() -> new ServiceException("该培训调查已不存在"));
        WxUserTrainSurvey wxUserTrainSurvey = wxUserTrainSurveyMapper.selectOne(new LambdaQueryWrapper<WxUserTrainSurvey>()
                .eq(WxUserTrainSurvey::getWxUserId, wxUserId)
                .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurveyIsPassDto.getTrainSurveyId())
                .eq(WxUserTrainSurvey::getExamStatus, 0));
        if (wxUserTrainSurvey == null) {
            throw new ServiceException("您不是本次调查的人员");
        }
        if (trainSurveyIsPassDto.getCurriculumSectionTopics() != null) {
            wxUserTrainSurvey.setTopicJson(JSONObject.toJSONString(trainSurveyIsPassDto.getCurriculumSectionTopics()));
        }
        wxUserTrainSurvey.setIsPass(1);
        wxUserTrainSurveyMapper.updateById(wxUserTrainSurvey);
        return new ReturnVO("培训调查结算成功", wxUserTrainSurvey.getId());
    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @SneakyThrows
    @Override
    public ReturnVO importTopicSection(String token, Long trainSurveyId, MultipartFile file) {
        //接口幂等处理
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(RedisConstants.TOPIC_IMPORT + token, token, 5, TimeUnit.SECONDS);
        if (!Boolean.TRUE.equals(aBoolean)) {
            throw new ServiceException("操作太频繁,请5秒后再试");
        }
        ExcelTopicUtils excelUtil = new ExcelTopicUtils();
        Workbook wb = excelUtil.getExcel(file);
        Sheet sheet = wb.getSheetAt(0);//读取sheet(从0计数)
        int rowNum = sheet.getLastRowNum();//读取行数(从0计数)
        int i = 0;
        try {
            Long topicId = null;//题目id
            CurriculumSectionTopic topic = null;//题目
            Long topicAnswerId = null;//答案id
            CurriculumSectionTopicAnswer topicAnswer = null;//答案选项
            for (; i <= rowNum; i++) {
                if (i < 1) {
                    //不读前两行
                    continue;
                }
                Row row = sheet.getRow(i);//获得行
                for (int j = 0; j < 7; j++) {
                    Cell cell = row.getCell(j);//获取单元格
                    //题目名称 如果题目名称为空 则让答案选项关联上一个题目数据
                    if (cell != null && StringUtils.isNotBlank(cell.toString())) {
                        //题目id
                        if (j == 0) {
                            topicId = Long.valueOf(cell.toString());
                        }
                        if (j == 1) {
                            topic = new CurriculumSectionTopic();
                            topic.setTopicCategory(2);
                            topic.setCurriculumSectionId(trainSurveyId);
                            topic.setTopicName(cell.toString());
                        }
                        //设置限制个数 对象最后的一个属性进行操作
                        if (j == 2) {
                            topic.setChooseNum(excelUtil.format(cell.toString()));
                            if (topicId == null) {
                                curriculumSectionTopicMapper.insert(topic);
                            } else {
                                topic.setId(topicId);
                                curriculumSectionTopicMapper.updateById(topic);
                                topicId = null;//置空
                            }
                        }
                        //答案id
                        if (j == 3) {
                            topicAnswerId = Long.valueOf(cell.toString());
                        }
                        //选项
                        if (j == 4) {
                            topicAnswer = new CurriculumSectionTopicAnswer();
                            topicAnswer.setCurriculumSectionTopicId(topic.getId());
                            topicAnswer.setItem(cell.toString());
                        }
                        //答案
                        if (j == 5) {
                            topicAnswer.setAnswer(cell.toString());
                        }
                        //分数
                        if (j == 6) {
                            topicAnswer.setScore(new BigDecimal(cell.toString()));
                            if (topicAnswerId == null) {
                                curriculumSectionTopicAnswerMapper.insert(topicAnswer);
                            } else {
                                topicAnswer.setId(topicAnswerId);
                                curriculumSectionTopicAnswerMapper.updateById(topicAnswer);
                                topicAnswerId = null;//置空
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("导入测评题库出错[{}]", e.getMessage());
            throw new ServiceException("第" + (i + 1) + "行出错");
        }
        return new ReturnVO("题库导入成功", null);
    }

    @Override
    public ReturnVO<List<JSONObject>> selectWxUserTrainSurvey(Long trainSurveyId, List<Long> wxUserIds) {
        List<JSONObject> wxUserTrainSurveys = Lists.newArrayList();
        for (Long wxUserId : wxUserIds) {
            //查询用户绑定可考的考试
            WxUserTrainSurvey wxUserTrainSurvey = wxUserTrainSurveyMapper.selectOne(new LambdaQueryWrapper<WxUserTrainSurvey>()
                    .eq(WxUserTrainSurvey::getTrainSurveyId, trainSurveyId)
                    .eq(WxUserTrainSurvey::getWxUserId, wxUserId)
                    .eq(WxUserTrainSurvey::getExamStatus, 0));
            if (wxUserTrainSurvey != null) {
                wxUserTrainSurveys.add(JSONObject.parseObject(JSONObject.toJSONString(wxUserTrainSurvey)));
            }
        }
        return new ReturnVO("查询培训调查绑定的用户", wxUserTrainSurveys);
    }
}
